package graphen;

import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.AffineTransform;
import java.util.Vector;
import javax.swing.JPanel;
import graphen.struktur.*;

public class GraphPanel extends JPanel implements MouseListener, MouseMotionListener{
  Graph graph;
  Vector<Point> where;
  private boolean positioned;
  
  public GraphPanel(Graph graph){
    this.setOpaque(false);
    this.graph=graph;
    int anz=graph.anzKnoten();
    where=new Vector<Point>(anz);
    positioned=false;
    addMouseListener(this);
  }
  
  private void randomPos(){
    int anz=graph.anzKnoten();
    int breit=getWidth();
    int hoch=getHeight();
    for(int i=0; i<anz; ++i){
      Point p=new Point((int)(Math.random()*(breit-10)), (int)(Math.random()*(hoch-10)));
      where.add(p);
    }
    positioned=true;
  }
  
  @Override
  public void paint(Graphics g){
    Graphics2D g2=(Graphics2D)g;
    if(!positioned) randomPos();
    FontMetrics fm=g.getFontMetrics();
    String[] namen=graph.alleKnotennamen();
    int kanz=namen.length;
    //Zeichne alle Kanten
    for(int i=0; i<kanz; ++i){
      Point from=where.get(i);
      int[] zielnr=graph.alleZieleVon(i);
      for(int j=zielnr.length-1; j>=0; --j){
        int z=zielnr[j];
        Point to=where.get(z);
        z=graph.getKosten(i,z);
        String s=(z==0?"":z)+"\u2192";
        paintKante(g2, from, to, s);
      }
    }
    //Zeichne die Knoten, verdecke Teile der Kanten
    for(int i=0; i<kanz; ++i)
      paintKnoten(g2, namen[i], where.get(i), fm);
  }
  
  private AffineTransform dreh=new AffineTransform();
  public void paintKante(Graphics2D g2, Point from, Point to, String s){
    g2.setColor(Color.BLUE);
    g2.drawLine(from.x, from.y, to.x, to.y);
    AffineTransform merk=g2.getTransform();
    double px=to.x-from.x, py=to.y-from.y;
    double theta=Math.atan2(py, px);
    px=(from.x+to.x)/2; py=(from.y+to.y)/2;
    dreh.setToRotation(theta, px, py);
    g2.setTransform(dreh);
    g2.drawString(s, (float)px, (float)py);
    g2.setTransform(merk);
  }
  
  public void paintKnoten(Graphics2D g2, String t, Point p, FontMetrics fm) {
    int x=p.x;
    int y=p.y;
    g2.setColor(Color.LIGHT_GRAY);
    int w=fm.stringWidth(t)+10;
    int h=fm.getHeight()+4;
    g2.fillRect(x-w/2, y-h/2, w, h);
    g2.setColor(Color.BLACK);
    g2.drawRect(x-w/2, y-h/2, w-1, h-1);
    g2.drawString(t, x-(w-10)/2, (y-(h-4)/2)+fm.getAscent());
  }

  private Point bewegt;
  @Override
  public void mousePressed(MouseEvent e){
    int x=e.getX();
    int y=e.getY();
    double min=Double.POSITIVE_INFINITY;
    for(Point p: where){
      double dx=x-p.x, dy=y-p.y;
      double dist=dx*dx+dy*dy;
      if(dist<min){
        min=dist;
        bewegt=p;
      }
    }
    addMouseMotionListener(this);
  }

  @Override
  public void mouseReleased(MouseEvent e){
    removeMouseMotionListener(this);
    bewegt=null;
  }

  @Override
  public void mouseDragged(MouseEvent e) {
    if(bewegt==null) return;
    bewegt.x=e.getX();
    bewegt.y=e.getY();
    repaint();
  }

  public void mouseMoved(MouseEvent e) {}
  public void mouseClicked(MouseEvent e){}
  public void mouseEntered(MouseEvent e){}
  public void mouseExited(MouseEvent e){}
}
